﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Krile.Forms.MainForm.Controls.Timeline
{
    public partial class Timeline : UserControl
    {
        TimelineMouseManager tmm;

        public Timeline()
        {
            InitializeComponent();
            scroller.SmallChange = 10;
            tmm = new TimelineMouseManager(timelineList);
            timelineList.SelectedChange += new EventHandler(ReqVPosApply);
            timelineList.ScrollChanged += new EventHandler(ReqVPosApply);
        }

        private static object aplClutchLocker = new object();
        private volatile bool applyClutch = false;

        internal Data.XStatus[] Statuses
        {
            get { return timelineList.Statuses; }
            set
            {
                int scrpos = timelineList.VPosMax - scroller.Value;
                timelineList.Statuses = value;
                if (!Core.Config.Timeline.ListBottomNewer && timelineList.SelectedIndex > -1)
                {
                    this.Invoke(new Action(() =>
                    {
                        int nv = timelineList.VPosMax - scrpos;
                        if (nv < 0) nv = 0;
                        scroller.Value = nv;
                    }));
                }
                else
                {
                    ReqVPosApply(null, null);
                }
                timelineList.StatusUpdateProcess();
            }
        }

        void ReqVPosApply(object sender, EventArgs e)
        {
            if (applyClutch) return;
            if (this.InvokeRequired)
            {
                this.Invoke(new EventHandler(ReqVPosApply), sender, e);
                return;
            }

            if (scroller.Maximum != timelineList.VPosMax)
                SetScrollMax();
            SetScrollFromList();
        }

        internal Data.XStatus SelectedStatus
        {
            get { return timelineList.SelectedStatus; }
        }

        internal void ClearSelect()
        {
            timelineList.SelectedIndex = -1;
        }

        internal int ScrollValue
        {
            get { return scroller.Value; }
            set
            {
                scroller.Value = value;
                timelineList.VerticalPosition = value;
            }
        }

        internal void InitScrollbar()
        {
            SetScrollFromList();
        }

        internal int ScrollbarWidth
        {
            get { return scroller.Width; }
            set { scroller.Width = value; }
        }

        private void SetScrollMax()
        {
            lock (scrClutchLocker)
            {
                scrollClutch = true;
                int maximum = timelineList.VPosMax;
                scroller.Maximum = maximum;
                if ((scroller.Enabled || scroller.Maximum == 0) && scroller.Value > maximum)
                {
                    scroller.Value = maximum;
                    ApplyScroll();
                }
                scrollClutch = false;
            }
        }
        
        private void SetScrollFromList()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(SetScrollFromList));
            }
            else
            {
                lock (scrClutchLocker)
                {
                    scrollClutch = true;
                    scroller.Value = timelineList.VerticalPosition;
                    scrollClutch = false;
                }
            }
        }

        private void ApplyScroll()
        {
            lock (aplClutchLocker)
            {
                applyClutch = true;
                timelineList.VerticalPosition = scroller.Value;
                applyClutch = false;
            }
        }

        private static object scrClutchLocker = new object();
        private volatile bool scrollClutch = false;

        private void scroller_Scroll(object sender, ScrollEventArgs e)
        {
            scroller_ValueChanged(sender, null);
        }

        private void scroller_ValueChanged(object sender, EventArgs e)
        {
            //check clutch
            if (scrollClutch) return;
            if (scroller.Maximum != timelineList.VPosMax)
            {
                SetScrollMax();
            }
            ApplyScroll();
        }

        public void FullRedraw()
        {
            timelineList.FullRedraw();
        }

        public void QuickRedraw()
        {
            timelineList.Refresh();
        }

        private void Timeline_Resize(object sender, EventArgs e)
        {
            scroller.LargeChange = this.Height;
        }

        public void EnsureVisible()
        {
            timelineList.EnsureVisible();
        }
    }
}
